﻿namespace MSpecTests.WhoCanHelpMe.Tasks
{
    #region Using Directives

    using System.Collections.Generic;
    using System.Linq;

    using global::WhoCanHelpMe.Domain;
    using global::WhoCanHelpMe.Domain.Contracts.Repositories;
    using global::WhoCanHelpMe.Domain.Specifications;
    using global::WhoCanHelpMe.Tasks;

    using Machine.Specifications;

    using Rhino.Mocks;

    #endregion

    public abstract class specification_for_search_tasks
    {
        protected static SearchTasks sut;

        protected static IAssertionRepository the_assertion_repository;

        private Establish context = () =>
        {
            the_assertion_repository = MockRepository.GenerateStub<IAssertionRepository>();
        };

        protected static void CreateSut()
        {
            sut = new SearchTasks(the_assertion_repository);
        }
    }

    public class when_the_search_tasks_are_asked_to_search_by_tag_name_and_there_are_matching_tags : specification_for_search_tasks
    {
        static IList<Assertion> result;

        static string the_tag_name;

        static IQueryable<Assertion> matching_tags;

        Establish context = () =>
            {
                the_tag_name = "tag name";

                matching_tags = new List<Assertion>
                    {
                        new Assertion { Profile = new Profile { LastName = "X" } },
                        new Assertion { Profile = new Profile { LastName = "A" } },
                        new Assertion { Profile = new Profile { LastName = "M" } }
                    }.AsQueryable();

                the_assertion_repository.StubFindAll().Return(matching_tags);

                CreateSut();
            };

        Because b = () => result = sut.ByTag(the_tag_name);

        It should_ask_the_assertion_repository_for_the_matching_assertions = () => the_assertion_repository.AssertFindAllWasCalledWithSpecification<AssertionByTagNameSpecification, Assertion>(s => s.TagName == the_tag_name);

        It should_return_the_list_of_matching_assertions = () => result.ShouldContainOnly(matching_tags);

        It should_sort_the_matching_assertions_by_profile_last_name = () =>
            {
                for (int index = 1; index < result.Count; index++)
                {
                    result[index - 1].Profile.LastName.ShouldBeLessThan(result[index].Profile.LastName);
                }
            };
    }

    public class when_the_search_tasks_are_asked_to_search_by_tag_name_and_there_are_no_matching_tags : specification_for_search_tasks
    {
        static IList<Assertion> result;

        static string the_tag_name;

        static IQueryable<Assertion> matching_tags;

        Establish context = () =>
        {
            the_tag_name = "tag name";

            matching_tags = new List<Assertion>().AsQueryable();

            the_assertion_repository.StubFindAll().Return(matching_tags);

            CreateSut();
        };

        Because b = () => result = sut.ByTag(the_tag_name);

        It should_ask_the_assertion_repository_for_the_matching_assertions = () => the_assertion_repository.AssertFindAllWasCalledWithSpecification<AssertionByTagNameSpecification, Assertion>(s => s.TagName == the_tag_name);

        It should_return_an_empty_list = () => result.ShouldBeEmpty();
    }

    public class when_the_search_tasks_are_asked_to_search_by_tag_id_and_there_are_matching_tags : specification_for_search_tasks
    {
        static IList<Assertion> result;

        static int the_tag_id;

        static IQueryable<Assertion> matching_tags;

        Establish context = () =>
        {
            the_tag_id = 12;

            matching_tags = new List<Assertion>
                    {
                        new Assertion { Profile = new Profile { LastName = "X" } },
                        new Assertion { Profile = new Profile { LastName = "A" } },
                        new Assertion { Profile = new Profile { LastName = "M" } }
                    }.AsQueryable();

            the_assertion_repository.StubFindAll().Return(matching_tags);

            CreateSut();
        };

        Because b = () => result = sut.ByTagId(the_tag_id);

        It should_ask_the_assertion_repository_for_the_matching_assertions = () => the_assertion_repository.AssertFindAllWasCalledWithSpecification<AssertionByTagIdSpecification, Assertion>(s => s.TagId == the_tag_id);

        It should_return_the_list_of_matching_assertions = () => result.ShouldContainOnly(matching_tags);

        It should_sort_the_matching_assertions_by_profile_last_name = () =>
        {
            for (int index = 1; index < result.Count; index++)
            {
                result[index - 1].Profile.LastName.ShouldBeLessThan(result[index].Profile.LastName);
            }
        };
    }

    public class when_the_search_tasks_are_asked_to_search_by_tag_id_and_there_are_no_matching_tags : specification_for_search_tasks
    {
        static IList<Assertion> result;

        static int the_tag_id;

        static IQueryable<Assertion> matching_tags;

        Establish context = () =>
        {
            the_tag_id = 12;

            matching_tags = new List<Assertion>().AsQueryable();

            the_assertion_repository.StubFindAll().Return(matching_tags);

            CreateSut();
        };

        Because b = () => result = sut.ByTagId(the_tag_id);

        It should_ask_the_assertion_repository_for_the_matching_assertions = () => the_assertion_repository.AssertFindAllWasCalledWithSpecification<AssertionByTagIdSpecification, Assertion>(s => s.TagId == the_tag_id);

        It should_return_an_empty_list = () => result.ShouldBeEmpty();
    }
}
